package org.zhao.nettydemos.lab06;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

/**
 * @Auther: xiaohui.zhao
 * @Date: 2021/9/17 15:41
 * @Description:  重现SimpleDateFormat类的线程安全问题
 *
 * 使用线程池结合Java并发包中的CountDownLatch类和
 * Semaphore类来重现线程安全问题。
 *
 * CountDownLatch类可以使一个线程等待其他线程各自执行完毕后再执行。而Semaphore类可以理解为一个计数信号量，必须
 * 由获取它的线程释放，经常用来限制访问某些资源的线程数量，例如限流等。
 *
 */
public class SimpleDateFormatTest01 {

    // 程序执行的总次数
    private static final int EXECUTE_COUNT = 1000;
    //同时运行的线程数量
    private static final int THREAD_COUNT = 20;

    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");

    public static void main(String[] args) throws InterruptedException {
        final Semaphore semaphore = new Semaphore(THREAD_COUNT);
        final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);

        ExecutorService executorService = Executors.newCachedThreadPool();

        for(int i=0;i<EXECUTE_COUNT;i++){

            executorService.execute(() -> {
                try{
                    semaphore.acquire();
                    try{
                        simpleDateFormat.parse("2020-01-01");
                        //System.out.println("格式化成功了一个呀 ");
                    }catch (ParseException e){
                        System.out.println("线程 "+Thread.currentThread().getName() + "格式化日期失败");
                        e.printStackTrace();
                        System.exit(1);
                    }catch (NumberFormatException e){
                        System.out.println("线程 "+Thread.currentThread().getName() + "格式化日期失败");
                        e.printStackTrace();
                        System.exit(1);
                    }
                    semaphore.release();
                }catch (InterruptedException e){
                    System.out.println("信号量发生错误");
                    e.printStackTrace();
                    System.exit(1);
                }
                countDownLatch.countDown();
            });
        }

        countDownLatch.await();
        executorService.shutdown();
        System.out.println("所有线程格式化日期成功");
    }

}